import { contextBridge, ipcRenderer } from 'electron'
import { electronAPI } from '@electron-toolkit/preload'
import { isPromise, randomEncodeStr } from '../utils'

const callFuncs = new Map()

const callFunc = (func) => {
  const callID = randomEncodeStr(12)
  callFuncs.set(callID, func)

  return {
    __callFunc: callID
  }
}

// Custom APIs for renderer
const api = {
  getPort: () => {
    return ipcRenderer.sendSync('get-port')
  },
  getProxyHost: () => {
    return ipcRenderer.sendSync('get-proxy-host')
  },
  setTeamId: (teamId) => {
    ipcRenderer.invoke('set-team-id', teamId)
  }
}

const client = {
  createBrowerView: async (url, bounds, option = {}) => {
    const viewID = randomEncodeStr(12)
    await ipcRenderer.invoke('createBrowerView', { viewID, url, bounds, option })

    return {
      viewID,
      url,
      bounds,
      ...[ 'destory', 'reload', 'forward', 'show', 'retreat', 'navigateTo', 'resize', 'beforeRequest', 'executeJavaScript', 'fetchCookies', 'clearCache', 'navigateDidEvent', 'finishLoadEvent'].reduce((methods, method) => {
        methods[method] = (...args) => {
          return ipcRenderer.invoke('browerViewCall', { viewID, method, args: args.map(arg => typeof arg === 'function' ? callFunc(arg) : arg)})
        }
        return methods
      }, {})
    }
  }
}

const autoUpdater = {
  checkForUpdates: () => {
    ipcRenderer.invoke('check-updater')
  },

  downloadUpdate: () => {
    ipcRenderer.invoke('download-update')
  },

  quitAndInstall: () => {
    ipcRenderer.invoke('quit-and-install')
  },

  on: (event, callback) => {
    ipcRenderer.invoke('auto-updater-event', { event, callback: callFunc(callback) })
  },
}

const proxyHost = api.getProxyHost()

// Use `contextBridge` APIs to expose Electron APIs to
// renderer only if context isolation is enabled, otherwise
// just add to the DOM global.
if (process.contextIsolated) {
  try {
    contextBridge.exposeInMainWorld('electron', electronAPI)
    contextBridge.exposeInMainWorld('api', api)
    contextBridge.exposeInMainWorld('client', client)
    contextBridge.exposeInMainWorld('autoUpdater', autoUpdater)
    contextBridge.exposeInMainWorld('callFunc', callFunc)
    contextBridge.exposeInMainWorld('ORGCOMMON_BASE_URL', proxyHost)
  } catch (error) {
    console.error(error)
  }
} else {
  window.electron = electronAPI
  window.api = api
  window.client = client
  window.autoUpdater = autoUpdater
  window.callFunc = callFunc
  window.ORGCOMMON_BASE_URL = proxyHost
}

ipcRenderer.on('callFunc', async (_, message) => {
  const { callID, args } = message
  const func = callFuncs.get(callID)

  if (func){
    const res = func(...args)

    if (isPromise(res)) {
      await res
    }
  }

  // callFuncs.delete(callID)
})
